//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "mem.h"
#include "types.h"
#include "serial.h"
#include "util.h"
#include "config.h"

int load_memory(char *optstr, u32 addr)
{
    u32 read;

    if (MyStrCmp(optstr, "-l", 2)) {
        read = *((u32 *)addr);
        printk("%08x\n", read);
    }
    else if (MyStrCmp(optstr, "-h", 2)) {
        read = *((u16 *)addr);
        printk("%04x\n", read);
    }
    else if (MyStrCmp(optstr, "-b", 2)) {
        read = *((u8 *)addr);
        printk("%02x\n", read);
    }
    else {
        printk("Invalid option string : -l, -h -b are valid\n");
    }
    return 1;
}

int store_memory(char *optstr, u32 addr, u32 val)
{
    if (MyStrCmp(optstr, "-l", 2)) {
        *((u32 *)addr) = (u32)val;
    }
    else if (MyStrCmp(optstr, "-h", 2)) {
        *((u16 *)addr) = (u16)val;
    }
    else if (MyStrCmp(optstr, "-b", 2)) {
        *((u8 *)addr) = (u8)val;
    }
    else {
        printk("Invalid option string : -l, -h -b are valid\n");
    }
    return 1;
}

void DumpMem(u32* address, u32 length)
{
    u32 i;
    u32 PrintAddress;

    PrintAddress = (((u32)address)/16)*16;

    printk("\n           ");
    printk("00000000 00000004 00000008 0000000c\n");

    for (i = 0; i <= (length-1) / 16; i++) {
        printk("0x%08x %08x %08x %08x %08x\n", PrintAddress, *((u32*)(PrintAddress)), *((u32*)(PrintAddress+4)), *((u32*)(PrintAddress+8)), *((u32*)(PrintAddress+12)));
        PrintAddress += 16;
    }
}

void CmpMem(u32 address1, u32 address2, u32 length)
{
    u32 equal;
    u32 i;

    equal=1;
    for (i = 0;i < length;i += 4) {
        if ((*(u32*)((u32)address1 + i)) != (*(u32*)((u32)address2 + i))) {
            printk("%08x : %08x, %08x : %08x\n",(u32)address1+i, *(u32*)((u32)address1+i), (u32)address2+i, *(u32*)((u32)address2+i));
            equal=0;
        }
    }

    if(equal==1) printk("Equal data\n");
}

/*
  Warning : pass of this test does not guarantee the complete operation of the SDRAM

  just copy a data to the address and check if the data is correct
  need more read/write pattern to test the SDRAM completely
*/
void ram_test(u32* address, int LengthInMB)
{
    u32 TestStartAddress;
    u32 i;

    TestStartAddress = (((u32)address)/4)*4;
    for (i = TestStartAddress;i < TestStartAddress + LengthInMB*0x100000L; i += 4) {
        if ((i >= RAM_START + RAM_BOOT_LOADER_AREA_START_OFFSET_FROM_RAM_START) && (i <= RAM_START + RAM_STACK_END_OFFSET_FROM_RAM_START)) {
            /* as for boot code area, do not test 
             * Even this cannot protect the boot code against the aliasing. so be careful.
             */
        }
        else {
            (*(u32*)i) = i+1;
        }
    }
    for (i = TestStartAddress;i < TestStartAddress + LengthInMB*0x100000L; i += 4) {
        if ((i >= RAM_START + RAM_BOOT_LOADER_AREA_START_OFFSET_FROM_RAM_START) && (i <= RAM_START + RAM_STACK_END_OFFSET_FROM_RAM_START)) {
            /* as for boot code area, do not test */
        }
        else {
            if ((*(u32*)i) != i + 1) {
                printk("RAM Error @ 0x%08x\n", i);
                return;
            }
        }
    }

    printk("RAM Test OK\n");
}
